package junit.generic.genetic.chromosome;

import static org.junit.Assert.*;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import generic.genetic.chromosome.PermutationChromosome;

import org.junit.Test;

public class PermutationChromosome_Mutation_Test {

	PermutationChromosome pc1;
	
	@Test
	public void mutation_inversion_test() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		
		pc1 = new PermutationChromosome(8);
		
		pc1.setPermutation(new int[]{4,5,2,1,8,7,6,3});
		
		Method method = PermutationChromosome.class.getDeclaredMethod("mutation_inversion", int.class, int.class);
		method.setAccessible(true);
		method.invoke(pc1,6,3);
		
		PermutationChromosome pc1_exp = (PermutationChromosome) pc1.getCopy();
		pc1_exp.setPermutation(new int[]{4,5,2,7,8,1,6,3});
		
		assertEquals("El cromosoma 1 resultante no es correcto", pc1_exp, pc1);
	}
	
	@Test
	public void mutation_exchange_test() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		
		pc1 = new PermutationChromosome(8);
		
		pc1.setPermutation(new int[]{4,5,2,1,8,7,6,3});
		
		Method method = PermutationChromosome.class.getDeclaredMethod("mutation_exchange", int.class, int.class);
		method.setAccessible(true);
		method.invoke(pc1,1,7);
		
		PermutationChromosome pc1_exp = (PermutationChromosome) pc1.getCopy();
		pc1_exp.setPermutation(new int[]{4,3,2,1,8,7,6,5});
		
		assertEquals("El cromosoma 1 resultante no es correcto", pc1_exp, pc1);
	}
	
	@Test
	public void mutation_insertion_test() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		
		pc1 = new PermutationChromosome(8);
		
		pc1.setPermutation(new int[]{4,5,2,1,8,7,6,3});
		
		Method method = PermutationChromosome.class.getDeclaredMethod("mutation_insertion", int.class, int.class);
		method.setAccessible(true);
		method.invoke(pc1,6,3);
		method.invoke(pc1,2,6);
		
		PermutationChromosome pc1_exp = (PermutationChromosome) pc1.getCopy();
		pc1_exp.setPermutation(new int[]{4,5,6,1,8,7,2,3});
		
		assertEquals("El cromosoma 1 resultante no es correcto", pc1_exp, pc1);
	}
	
	@Test
	public void mutation_heuristic_test() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		
		pc1 = new PermutationChromosome(8){
			public float evaluate() { 
				int[] perm = getPermutation();
				int tmp = 0;
				for (int i=0;i<nGenes;i++){
					tmp *= 10;
					tmp += perm[i];
				}
				return tmp; 
			}
		};
		
		pc1.setPermutation(new int[]{4,5,2,1,8,7,6,3});
		
		Method method = PermutationChromosome.class.getDeclaredMethod("mutation_heuristic", int[].class);
		method.setAccessible(true);
		method.invoke(pc1,new int[]{6,3,2});
		
		PermutationChromosome pc1_exp = (PermutationChromosome) pc1.getCopy();
		pc1_exp.setPermutation(new int[]{4,5,1,2,8,7,6,3});
		
		assertEquals("El cromosoma 1 resultante no es correcto", pc1_exp, pc1);
	}
	
	@Test
	public void mutation_shuffle_test_even() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		
		pc1 = new PermutationChromosome(8);
		
		pc1.setPermutation(new int[]{4,5,2,1,8,7,6,3});
		
		Method method = PermutationChromosome.class.getDeclaredMethod("mutation_shuffle");
		method.setAccessible(true);
		method.invoke(pc1);
		
		PermutationChromosome pc1_exp = (PermutationChromosome) pc1.getCopy();
		pc1_exp.setPermutation(new int[]{4,8,5,7,2,6,1,3});
		
		assertEquals("El cromosoma 1 resultante no es correcto", pc1_exp, pc1);
	}
	
	@Test
	public void mutation_shuffle_test_odd() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		
		pc1 = new PermutationChromosome(9);
		
		pc1.setPermutation(new int[]{3,0,1,7,6,5,8,2,4});
		
		Method method = PermutationChromosome.class.getDeclaredMethod("mutation_shuffle");
		method.setAccessible(true);
		method.invoke(pc1);
		
		PermutationChromosome pc1_exp = (PermutationChromosome) pc1.getCopy();
		pc1_exp.setPermutation(new int[]{3,5,0,8,1,2,7,4,6});
		
		assertEquals("El cromosoma 1 resultante no es correcto", pc1_exp, pc1);
	}

}
